package com.neusoft.neuiotms.dcvm.task;

import java.text.ParseException;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.neusoft.neuiotms.dcvm.bean.AttrBean;
import com.neusoft.neuiotms.dcvm.bean.StandardCiBean;
import com.neusoft.neuiotms.dcvm.model.Alarm;
import com.neusoft.neuiotms.dcvm.repository.AlarmRepository;
import com.neusoft.neuiotms.dcvm.service.AlarmService;
import com.neusoft.neuiotms.dcvm.service.AssetService;

import lombok.extern.slf4j.Slf4j;

/**
 * IDC 综合运管平台告警管理接口
 *
 * @author sunchf
 */
@Slf4j
@Service
public class IdcAlarmPullService {

    private static ParameterizedTypeReference<List<Map<String, Object>>> typeRef =
            new ParameterizedTypeReference<List<Map<String, Object>>>() {
            };

    private static Map<String, String> alarmLevelMap = Maps.newHashMap();
    static {
        IdcAlarmPullService.alarmLevelMap.put("一级告警", "1");
        IdcAlarmPullService.alarmLevelMap.put("二级告警", "2");
        IdcAlarmPullService.alarmLevelMap.put("三级告警", "3");
        IdcAlarmPullService.alarmLevelMap.put("四级告警", "4");
    }

    @Value("${idcAlarmUrl:http://localhost}")
    private String remoteUrL;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private AlarmService alarmService;
    @Autowired
    private AlarmRepository alarmRepository;
    @Autowired
    private AssetService assetService;

    @Transactional
    public void start(List<String> roomCodes, List<String> alarmLevel, List<String> alarmType,
            List<String> alarmStatus, int size) {
        final String today = DateFormatUtils.format(Calendar.getInstance(), "yyyy-MM-dd");
        final String nonce = "ns8088";
        final String signature = DigestUtils.md5Hex("key=" + today + "&nonce=" + nonce);

        final Map<String, Object> reqBody = Maps.newHashMap();
        reqBody.put("nonce", nonce);
        reqBody.put("signature", signature);
        reqBody.put("roomCodes", roomCodes);
        reqBody.put("alarmLevel", alarmLevel);
        reqBody.put("alarmType", alarmType);
        reqBody.put("alarmStatus", alarmStatus);
        reqBody.put("size", size);
        final HttpEntity<Map<String, Object>> request = new HttpEntity<>(reqBody);
        final ResponseEntity<List<Map<String, Object>>> response = this.restTemplate
                .exchange(this.remoteUrL, HttpMethod.POST,
                        request,
                        IdcAlarmPullService.typeRef);

        final List<Map<String, Object>> results = response.getBody();
        IdcAlarmPullService.log.info("拉取IDC告警数量：{}", results.size());
        if (IdcAlarmPullService.log.isDebugEnabled()) {
            IdcAlarmPullService.log.debug("拉取IDC告警结果：{}", JSON.toJSONString(results));
        }

        final List<Alarm> newAlarms = Lists.newArrayList();
        for (final Map<String, Object> r : results) {
            final Alarm a = new Alarm();
            a.setAlarmContent((String) r.get("content"));
            a.setAlarmId(this.buildAlarmId(String.valueOf(r.get("alarmId"))));
            a.setAssetCode((String) r.get("deviceCode"));
            a.setAlarmLevel(
                    IdcAlarmPullService.alarmLevelMap.containsKey(
                            r.get("alarmLevel")) ? IdcAlarmPullService.alarmLevelMap.get(r.get("alarmLevel")) : "2");
            try {
                a.setAlarmTime(DateUtils.parseDate((String) r.get("alarmTime"), "yyyy-MM-dd HH:mm:ss"));
            } catch (final ParseException e) {
                a.setAlarmTime(Calendar.getInstance().getTime());
            }
            a.setSourceType(2);

            try {
                final StandardCiBean alarmAssetCi = this.assetService.getCiDetail(a.getAssetCode());
                a.setAssetName(alarmAssetCi.getName());
                final Optional<AttrBean> alarmAssetLocation =
                        alarmAssetCi.getAttrs().stream().filter(attr -> "location".equals(attr.getKey())).findAny();

                if (alarmAssetLocation.isPresent()) {
                    final StandardCiBean locationCi =
                            this.assetService.getCiDetail(String.valueOf(alarmAssetLocation.get().getValue()));
                    a.setLocationCode(locationCi.getCode());
                    a.setLocationName(locationCi.getName());
                }

                final Optional<AttrBean> cabinetAttr =
                        alarmAssetCi.getAttrs().stream().filter(it -> "cabinet".equals(it.getKey())).findAny();
                if (cabinetAttr.isPresent()) {
                    a.setCabinetCode((String) cabinetAttr.get().getValue());

                    try {
                        final StandardCiBean cabinetCi = this.assetService.getCiDetail(a.getCabinetCode());
                        a.setCabinetName(cabinetCi.getName());
                        final Optional<AttrBean> cabinetLocation =
                                cabinetCi.getAttrs().stream().filter(attr -> "location".equals(attr.getKey()))
                                        .findAny();

                        if (cabinetLocation.isPresent()) {
                            final StandardCiBean locationCi =
                                    this.assetService.getCiDetail(String.valueOf(cabinetLocation.get().getValue()));
                            a.setLocationCode(locationCi.getCode());
                            a.setLocationName(locationCi.getName());
                        }

                    } catch (final Exception e) {
                    }

                }
                newAlarms.add(a);

            } catch (final Exception e) {
                IdcAlarmPullService.log.error("", e);
            }

        }

        this.alarmService.deleteBySourceType(2);
        this.alarmRepository.saveAll(newAlarms);
    }

    private String buildAlarmId(String alarmId) {
        return "IDC_ALARM_" + alarmId;
    }

}
